using Microsoft.AspNetCore.SignalR;
using ColaFlow.API.Hubs;

namespace ColaFlow.API.Services;

public class RealtimeNotificationService : IRealtimeNotificationService
{
    private readonly IHubContext<ProjectHub> _projectHubContext;
    private readonly IHubContext<NotificationHub> _notificationHubContext;
    private readonly ILogger<RealtimeNotificationService> _logger;

    public RealtimeNotificationService(
        IHubContext<ProjectHub> projectHubContext,
        IHubContext<NotificationHub> notificationHubContext,
        ILogger<RealtimeNotificationService> logger)
    {
        _projectHubContext = projectHubContext;
        _notificationHubContext = notificationHubContext;
        _logger = logger;
    }

    public async Task NotifyProjectCreated(Guid tenantId, Guid projectId, object project)
    {
        var tenantGroupName = $"tenant-{tenantId}";

        _logger.LogInformation("Notifying tenant {TenantId} of new project {ProjectId}", tenantId, projectId);

        await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("ProjectCreated", project);
    }

    public async Task NotifyProjectUpdated(Guid tenantId, Guid projectId, object project)
    {
        var projectGroupName = $"project-{projectId}";
        var tenantGroupName = $"tenant-{tenantId}";

        _logger.LogInformation("Notifying project {ProjectId} updated", projectId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("ProjectUpdated", project);
        await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("ProjectUpdated", project);
    }

    public async Task NotifyProjectArchived(Guid tenantId, Guid projectId)
    {
        var projectGroupName = $"project-{projectId}";
        var tenantGroupName = $"tenant-{tenantId}";

        _logger.LogInformation("Notifying project {ProjectId} archived", projectId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("ProjectArchived", new { ProjectId = projectId });
        await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("ProjectArchived", new { ProjectId = projectId });
    }

    public async Task NotifyProjectUpdate(Guid tenantId, Guid projectId, object data)
    {
        var groupName = $"project-{projectId}";

        _logger.LogInformation("Sending project update to group {GroupName}", groupName);

        await _projectHubContext.Clients.Group(groupName).SendAsync("ProjectUpdated", data);
    }

    // Epic notifications
    public async Task NotifyEpicCreated(Guid tenantId, Guid projectId, Guid epicId, object epic)
    {
        var projectGroupName = $"project-{projectId}";
        var tenantGroupName = $"tenant-{tenantId}";

        _logger.LogInformation("Notifying epic {EpicId} created in project {ProjectId}", epicId, projectId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("EpicCreated", epic);
        await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("EpicCreated", epic);
    }

    public async Task NotifyEpicUpdated(Guid tenantId, Guid projectId, Guid epicId, object epic)
    {
        var projectGroupName = $"project-{projectId}";

        _logger.LogInformation("Notifying epic {EpicId} updated", epicId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("EpicUpdated", epic);
    }

    public async Task NotifyEpicDeleted(Guid tenantId, Guid projectId, Guid epicId)
    {
        var projectGroupName = $"project-{projectId}";

        _logger.LogInformation("Notifying epic {EpicId} deleted", epicId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("EpicDeleted", new { EpicId = epicId });
    }

    // Story notifications
    public async Task NotifyStoryCreated(Guid tenantId, Guid projectId, Guid epicId, Guid storyId, object story)
    {
        var projectGroupName = $"project-{projectId}";
        var tenantGroupName = $"tenant-{tenantId}";

        _logger.LogInformation("Notifying story {StoryId} created in epic {EpicId}", storyId, epicId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("StoryCreated", story);
        await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("StoryCreated", story);
    }

    public async Task NotifyStoryUpdated(Guid tenantId, Guid projectId, Guid epicId, Guid storyId, object story)
    {
        var projectGroupName = $"project-{projectId}";

        _logger.LogInformation("Notifying story {StoryId} updated", storyId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("StoryUpdated", story);
    }

    public async Task NotifyStoryDeleted(Guid tenantId, Guid projectId, Guid epicId, Guid storyId)
    {
        var projectGroupName = $"project-{projectId}";

        _logger.LogInformation("Notifying story {StoryId} deleted", storyId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("StoryDeleted", new { StoryId = storyId });
    }

    // Task notifications
    public async Task NotifyTaskCreated(Guid tenantId, Guid projectId, Guid storyId, Guid taskId, object task)
    {
        var projectGroupName = $"project-{projectId}";
        var tenantGroupName = $"tenant-{tenantId}";

        _logger.LogInformation("Notifying task {TaskId} created in story {StoryId}", taskId, storyId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskCreated", task);
        await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("TaskCreated", task);
    }

    public async Task NotifyTaskUpdated(Guid tenantId, Guid projectId, Guid storyId, Guid taskId, object task)
    {
        var projectGroupName = $"project-{projectId}";

        _logger.LogInformation("Notifying task {TaskId} updated", taskId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskUpdated", task);
    }

    public async Task NotifyTaskDeleted(Guid tenantId, Guid projectId, Guid storyId, Guid taskId)
    {
        var projectGroupName = $"project-{projectId}";

        _logger.LogInformation("Notifying task {TaskId} deleted", taskId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskDeleted", new { TaskId = taskId });
    }

    public async Task NotifyTaskAssigned(Guid tenantId, Guid projectId, Guid taskId, Guid assigneeId)
    {
        var projectGroupName = $"project-{projectId}";

        _logger.LogInformation("Notifying task {TaskId} assigned to {AssigneeId}", taskId, assigneeId);

        await _projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskAssigned", new
        {
            TaskId = taskId,
            AssigneeId = assigneeId,
            AssignedAt = DateTime.UtcNow
        });
    }

    public async Task NotifyIssueCreated(Guid tenantId, Guid projectId, object issue)
    {
        var groupName = $"project-{projectId}";

        await _projectHubContext.Clients.Group(groupName).SendAsync("IssueCreated", issue);
    }

    public async Task NotifyIssueUpdated(Guid tenantId, Guid projectId, object issue)
    {
        var groupName = $"project-{projectId}";

        await _projectHubContext.Clients.Group(groupName).SendAsync("IssueUpdated", issue);
    }

    public async Task NotifyIssueDeleted(Guid tenantId, Guid projectId, Guid issueId)
    {
        var groupName = $"project-{projectId}";

        await _projectHubContext.Clients.Group(groupName).SendAsync("IssueDeleted", new { IssueId = issueId });
    }

    public async Task NotifyIssueStatusChanged(
        Guid tenantId,
        Guid projectId,
        Guid issueId,
        string oldStatus,
        string newStatus)
    {
        var groupName = $"project-{projectId}";

        await _projectHubContext.Clients.Group(groupName).SendAsync("IssueStatusChanged", new
        {
            IssueId = issueId,
            OldStatus = oldStatus,
            NewStatus = newStatus,
            ChangedAt = DateTime.UtcNow
        });
    }

    public async Task NotifyUser(Guid userId, string message, string type = "info")
    {
        var userConnectionId = $"user-{userId}";

        await _notificationHubContext.Clients.User(userId.ToString()).SendAsync("Notification", new
        {
            Message = message,
            Type = type,
            Timestamp = DateTime.UtcNow
        });
    }

    public async Task NotifyUsersInTenant(Guid tenantId, string message, string type = "info")
    {
        var groupName = $"tenant-{tenantId}";

        await _notificationHubContext.Clients.Group(groupName).SendAsync("Notification", new
        {
            Message = message,
            Type = type,
            Timestamp = DateTime.UtcNow
        });
    }
}
