using SameBeat.Domain.Wyjatki;
namespace SameBeat.Domain.Encje;
///
/// Log/audyt przyznan mikrofonu (ETAP 5) -- KAZDE przyznanie mikrofonu zostawia tu jeden wiersz,
/// niezaleznie od tego, czy sie skonczylo timerem czy hostem przerywajacym recznie. To NIE jest zywy
/// stan (ten siedzi na Wydarzenie.AktywnyMikrofonUczestnikId/AktywnyMikrofonKoniecUtc) -- zgodnie z
/// zasada "nie zapisuj kazdego pakietu WebRTC do bazy, baza przechowuje stan biznesowy": tu zapisujemy
/// tylko fakt biznesowy "kto, kiedy i na jak dlugo dostal mikrofon", raz na przyznanie.
///
public class HistoriaMikrofonu
{
public Guid Id { get; private set; }
public Guid WydarzenieId { get; private set; }
public Guid UczestnikOczekujacyId { get; private set; }
public DateTime StartUtc { get; private set; }
public DateTime KoniecPlanowanyUtc { get; private set; }
///
/// Kiedy mikrofon FAKTYCZNIE zostal odebrany -- null dopoki jest aktywny. Rozni sie od
/// KoniecPlanowanyUtc, gdy host przerwal recznie przed czasem (wtedy KoniecFaktycznyUtc <
/// KoniecPlanowanyUtc); rowny (z dokladnoscia do czestotliwosci timera) przy naturalnym wygasnieciu.
///
public DateTime? KoniecFaktycznyUtc { get; private set; }
public int CzasSekundy { get; private set; }
/// Nick hosta, ktory przyznal mikrofon -- do audytu (kto z ekipy to zrobil), nie do logiki.
public string PrzyznalHostNick { get; private set; } = string.Empty;
// Prywatny konstruktor bez parametrow -- wymagany przez EF Core do materializacji encji z bazy.
private HistoriaMikrofonu()
{
}
private HistoriaMikrofonu(Guid id, Guid wydarzenieId, Guid uczestnikOczekujacyId, DateTime startUtc, int czasSekundy, string przyznalHostNick)
{
Id = id;
WydarzenieId = wydarzenieId;
UczestnikOczekujacyId = uczestnikOczekujacyId;
StartUtc = startUtc;
KoniecPlanowanyUtc = startUtc.AddSeconds(czasSekundy);
CzasSekundy = czasSekundy;
PrzyznalHostNick = przyznalHostNick;
}
///
/// Otwiera nowy wpis audytu w chwili przyznania mikrofonu -- StartUtc/KoniecPlanowanyUtc licza
/// sie z tej samej chwili, co Wydarzenie.PrzyznajMikrofon (serwis wywoluje oba tuz obok siebie).
///
public static HistoriaMikrofonu Rozpocznij(Guid wydarzenieId, Guid uczestnikOczekujacyId, int czasSekundy, string przyznalHostNick)
{
if (wydarzenieId == Guid.Empty)
{
throw new NieprawidlowyStanEncjiWyjatek("Historia mikrofonu musi byc powiazana z konkretnym wydarzeniem.");
}
if (uczestnikOczekujacyId == Guid.Empty)
{
throw new NieprawidlowyStanEncjiWyjatek("Historia mikrofonu musi byc powiazana z konkretnym uczestnikiem.");
}
if (czasSekundy <= 0)
{
throw new NieprawidlowyStanEncjiWyjatek("Czas przyznania mikrofonu musi byc dodatni.");
}
var hostNickPrzyciety = string.IsNullOrWhiteSpace(przyznalHostNick) ? "nieznany" : przyznalHostNick.Trim();
return new HistoriaMikrofonu(Guid.NewGuid(), wydarzenieId, uczestnikOczekujacyId, DateTime.UtcNow, czasSekundy, hostNickPrzyciety);
}
/// Zamyka wpis w chwili faktycznego odebrania mikrofonu. Idempotentne -- druga zamiana nic nie zmienia.
public void Zakoncz()
{
if (KoniecFaktycznyUtc is not null)
{
return;
}
KoniecFaktycznyUtc = DateTime.UtcNow;
}
}