using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Domain.Entities.Members.ValueObject; namespace Domain.Entities.Members; /// /// 1회 방송 세션 (라이브 시작~종료) — YouTube 라이브 지표 수집 단위 /// public sealed class BroadcastSession { [ForeignKey(nameof(ChannelID))] public Channel Channel { get; private set; } = null!; [Key] public int ID { get; private set; } public int ChannelID { get; private set; } public BroadcastPlatform Platform { get; private set; } = BroadcastPlatform.YouTube; public string VideoID { get; private set; } = default!; public string? Title { get; private set; } public DateTime? StartAt { get; private set; } public DateTime? EndAt { get; private set; } public int DurationSec { get; private set; } public long FinalViews { get; private set; } public long FinalLikes { get; private set; } public bool IsFinalized { get; private set; } public DateTime? UpdatedAt { get; private set; } public DateTime CreatedAt { get; private set; } = DateTime.UtcNow; private BroadcastSession() { } private BroadcastSession(int channelID, BroadcastPlatform platform, string videoID) { if (channelID <= 0) { throw new ArgumentOutOfRangeException(nameof(channelID)); } if (string.IsNullOrWhiteSpace(videoID)) { throw new ArgumentException("VideoID is required.", nameof(videoID)); } ChannelID = channelID; Platform = platform; VideoID = videoID; } public static BroadcastSession Create(int channelID, BroadcastPlatform platform, string videoID) { return new(channelID, platform, videoID); } public void UpdateStats( string? title, DateTime? startAt, DateTime? endAt, long finalViews, long finalLikes ) { Title = title; StartAt = startAt; EndAt = endAt; if (startAt.HasValue && endAt.HasValue && endAt.Value > startAt.Value) { DurationSec = (int)(endAt.Value - startAt.Value).TotalSeconds; } FinalViews = finalViews; FinalLikes = finalLikes; UpdatedAt = DateTime.UtcNow; } public void MarkFinalized() { IsFinalized = true; UpdatedAt = DateTime.UtcNow; } }