using Monitoring.Core.Domain.AssetManagement;
using Monitoring.Core.Domain.EventManagement;
using Monitoring.Core.Domain.UserLogManagement;

namespace Monitoring.Features.Reports.Contracts;

/// <summary>
/// Логи по объекту
/// </summary>
public class LogGroupModel
{
	public Guid AssetId { get; init; }
	public string AssetName { get; init; }
	public int TotalRecordCount { get; init; }
	public int TotalAlarmCount { get; init; }
	public IEnumerable<DayLogModel> Days { get; init; }
	public IEnumerable<UserActivity> Users { get; init; }

	public LogGroupModel() { }

	public LogGroupModel(
		Guid assetId,
		string assetName,
		int totalRecordCount,
		int totalAlarmCount,
		IEnumerable<DayLogModel> days,
		IEnumerable<UserActivity> users)
	{
		AssetId = assetId;
		AssetName = assetName;
		TotalRecordCount = totalRecordCount;
		TotalAlarmCount = totalAlarmCount;
		Days = days;
		Users = users;
	}

	public class Combined
	{
		public AssetId AssetId { get; init; }
		public Asset Asset { get; init; }
		public DateTime CreatedAt { get; init; }
		public Event? Event { get; init; }
		public UserLog? UserLog { get; init; }

		public Combined(AssetId assetId, Asset asset, DateTime createdAt, Event? @event, UserLog? userLog)
		{
			AssetId = assetId;
			Asset = asset;
			CreatedAt = createdAt;
			Event = @event;
			UserLog = userLog;
		}
	}

	public static LogGroupModel FromEvent(IGrouping<Asset, Event> groupedEvents)
	{
		return new LogGroupModel(
			groupedEvents.Key.Id.Value,
			groupedEvents.Key.Name.Value,
			groupedEvents.Count(),
			groupedEvents.Count(x => x.Alarms.Count != 0),
			groupedEvents
				.GroupBy(x => x.CreatedAt.Date)
				.Select(DayLogModel.FromEvent),
			Array.Empty<UserActivity>()
		);
	}

	public static LogGroupModel FromUserLog(IGrouping<Asset, UserLog> groupedEvents)
	{
		return new LogGroupModel(
			groupedEvents.Key.Id.Value,
			groupedEvents.Key.Name.Value,
			groupedEvents.Count(),
			0,
			groupedEvents
				.GroupBy(x => x.CreatedAt.Date)
				.Select(DayLogModel.FromUserLog),
			groupedEvents
				.Where(x => x.UserId != null)
				.Select(x => new UserActivity
				{
					Name = x.User!.Username.Value,
					LogCount = groupedEvents.Count(y => y.UserId == x.UserId)
				})
				.Distinct()
				.OrderBy(x => x)
		);
	}

	internal static LogGroupModel FromCombined(IGrouping<AssetId, Combined> g)
	{
		var first = g.First();
		return new LogGroupModel(
			first.Asset.Id.Value,
			first.Asset.Name.Value,
			g.Count(),
			g.Count(x => x.Event?.Code.IsActive == true),
			g
				.GroupBy(x => x.CreatedAt.Date)
				.Select(DayLogModel.FromCombined),
			g
				.Where(x => x.UserLog?.UserId != null)
				.GroupBy(x => x.UserLog!.UserId)
				.Select(x => new UserActivity
				{
					Name = x.First().UserLog?.User.Username.Value ?? string.Empty,
					LogCount = x.Count()
				})
				.Distinct()
				.OrderBy(x => x.Name)
		);
	}
}
